﻿using AutoMapper;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Workflow2211A.Application.DTO.Inputs.IndependentBilling;
using Workflow2211A.Application.DTO.Outputs.IndependentBilling;
using Workflow2211A.Domain;
using Workflow2211A.Domain.IndependentBilling.CheckupItem;
using Workflow2211A.Domain.IndependentBilling.DrugCategory;
using Workflow2211A.Domain.IndependentBilling.MedicalInstitution;
using Workflow2211A.Domain.IndependentBilling.PrescriptionApplication;
using Workflow2211A.Domain.IndependentBilling.ShoppingCart;
using Workflow2211A.Domain.IndependentBilling.TestItem;
using Workflow2211A.Domain.RBAC;

namespace Workflow2211A.Application.Services.IndependentBilling
{
    /// <summary>
    /// 开单管理
    /// </summary>
    public class BillingServices : IBillingServices
    {
        #region 成员变量
        /// <summary>
        /// 用户仓储
        /// </summary>
        private readonly IBaseRepository<MedicalInstitutionModel> _medicalRepository;
        /// <summary>
        /// 药品分类仓储
        /// </summary>
        private readonly IBaseRepository<DrugCategoryModel> _drugCategoryRepository;
        /// <summary>
        /// 药品信息仓储
        /// </summary>
        private readonly IBaseRepository<DrugInfoModel> _drugInfoRepository;
        /// <summary>
        /// 检查项目分类仓储
        /// </summary>
        private readonly IBaseRepository<CheckupCategoryModel> _checkupCategoryRepository;
        /// <summary>
        /// 检查项目信息仓储
        /// </summary>
        private readonly IBaseRepository<CheckupItemModel> _checkupItemRepository;
        /// <summary>
        /// 检验项目分类仓储
        /// </summary>
        private readonly IBaseRepository<TestCategoryModel> _testCategoryRepository;
        /// <summary>
        /// 检验项目信息仓储
        /// </summary>
        private readonly IBaseRepository<TestItemModel> _testItemRepository;
        /// <summary>
        /// 购物车仓储
        /// </summary>
        private readonly IBaseRepository<ShoppingCartModel> _shoppingCartRepository;
        /// <summary>
        /// 购物车项目仓储
        /// </summary>
        private readonly IBaseRepository<CartItemModel> _cartItemRepository;
        /// <summary>
        /// 开单申请仓储
        /// </summary>
        private readonly IBaseRepository<PrescriptionApplicationModel> _prescriptionRepository;
        /// <summary>
        /// 开单明细仓储
        /// </summary>
        private readonly IBaseRepository<PrescriptionDetailModel> _prescriptionDetailRepository;
        /// <summary>
        /// AutoMapper
        /// </summary>
        private readonly IMapper _mapper;
        #endregion

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="medicalRepository">开单仓储</param>
        /// <param name="mapper">AutoMapper</param>
        public BillingServices(
            IBaseRepository<MedicalInstitutionModel> medicalRepository, 
            IBaseRepository<DrugCategoryModel> drugCategoryRepository,
            IBaseRepository<DrugInfoModel> drugInfoRepository,
            IBaseRepository<CheckupCategoryModel> checkupCategoryRepository,
            IBaseRepository<CheckupItemModel> checkupItemRepository,
            IBaseRepository<TestCategoryModel> testCategoryRepository,
            IBaseRepository<TestItemModel> testItemRepository,
            IBaseRepository<ShoppingCartModel> shoppingCartRepository,
            IBaseRepository<CartItemModel> cartItemRepository,
            IBaseRepository<PrescriptionApplicationModel> prescriptionRepository,
            IBaseRepository<PrescriptionDetailModel> prescriptionDetailRepository,
            IMapper mapper)
        {
            _medicalRepository = medicalRepository;
            _drugCategoryRepository = drugCategoryRepository;
            _drugInfoRepository = drugInfoRepository;
            _checkupCategoryRepository = checkupCategoryRepository;
            _checkupItemRepository = checkupItemRepository;
            _testCategoryRepository = testCategoryRepository;
            _testItemRepository = testItemRepository;
            _shoppingCartRepository = shoppingCartRepository;
            _cartItemRepository = cartItemRepository;
            _prescriptionRepository = prescriptionRepository;
            _prescriptionDetailRepository = prescriptionDetailRepository;
            _mapper = mapper;
        }
        /// <summary>
        /// 获取所有机构
        /// </summary>
        /// <returns>医疗机构列表</returns>
        public List<MedicalInstitutionModel> ShowMedicalInstitution()
        {
            // 通过仓储层获取所有医疗机构数据
            var medicalInstitutions = _medicalRepository.GetAll().ToList();
            return medicalInstitutions;
        }

        /// <summary>
        /// 根据药品分类名称查询药品信息
        /// </summary>
        /// <param name="categoryName">药品分类名称</param>
        /// <returns>药品信息列表</returns>
        public List<DrugInfoOutput> GetDrugsByCategoryName(string categoryName)
        {
            // 通过LINQ进行两表联查
            var query = from drug in _drugInfoRepository.GetAll()
                        join category in _drugCategoryRepository.GetAll()
                        on drug.DrugCategoryId equals category.Id
                        where category.CategoryName.Contains(categoryName)
                        select new DrugInfoOutput
                        {
                            Id = drug.Id,
                            DrugCategoryId = drug.DrugCategoryId,
                            CategoryName = category.CategoryName,
                            DrugName = drug.DrugName,
                            Dosage = drug.Dosage,
                            Effect = drug.Effect,
                            Price = drug.Price,
                            IsPrescription = drug.IsPrescription,
                            LimitQuantity = drug.LimitQuantity,
                            DrugImage = drug.DrugImage,
                            Quantity = drug.Quantity
                        };

            return query.ToList();
        }

        /// <summary>
        /// 根据检查项目分类名称查询检查项目信息
        /// </summary>
        /// <param name="checkupCategoryName">检查项目分类名称</param>
        /// <returns>检查项目信息列表</returns>
        public List<CheckupItemOutput> GetCheckupItemsByCategoryName(string checkupCategoryName)
        {
            // 通过LINQ进行两表联查
            var query = from item in _checkupItemRepository.GetAll()
                        join category in _checkupCategoryRepository.GetAll()
                        on item.CheckupItemCategoryId equals category.Id
                        where category.CheckupCategoryName.Contains(checkupCategoryName)
                        select new CheckupItemOutput
                        {
                            Id = item.Id,
                            CheckupItemCategoryId = item.CheckupItemCategoryId,
                            CheckupCategoryName = category.CheckupCategoryName,
                            CheckupItemName = item.CheckupItemName,
                            Price = item.Price,
                            Notes = item.Notes,
                            Quantity = item.Quantity
                        };

            return query.ToList();
        }

        /// <summary>
        /// 根据检验项目分类名称查询检验项目信息
        /// </summary>
        /// <param name="testCategoryName">检验项目分类名称</param>
        /// <returns>检验项目信息列表</returns>
        public List<TestItemOutput> GetTestItemsByCategoryName(string testCategoryName)
        {
            // 通过LINQ进行两表联查
            var query = from item in _testItemRepository.GetAll()
                        join category in _testCategoryRepository.GetAll()
                        on item.TestItemTypeId equals category.Id
                        where category.TestCategoryName.Contains(testCategoryName)
                        select new TestItemOutput
                        {
                            Id = item.Id,
                            TestItemTypeId = item.TestItemTypeId,
                            TestCategoryName = category.TestCategoryName,
                            TestItem = item.TestItem,
                            Price = item.Price,
                            Quantity = item.Quantity
                        };

            return query.ToList();
        }

        

        /// <summary>
        /// 添加开单申请
        /// </summary>
        /// <param name="prescriptionDTO">开单申请信息</param>
        /// <returns>开单申请ID</returns>
        public long AddPrescriptionApplication(PrescriptionApplicationDTO prescriptionDTO)
        {
            // 1. 参数检查
            if (prescriptionDTO == null)
                throw new ArgumentNullException(nameof(prescriptionDTO), "开单申请信息不能为空");
            
            if (prescriptionDTO.Details == null || !prescriptionDTO.Details.Any())
                throw new ArgumentException("开单申请必须包含至少一个明细项目");
            
            try
            {
                // 2. 创建开单申请
                var prescription = new PrescriptionApplicationModel();
                prescription.HospitalAreaId = prescriptionDTO.HospitalAreaId;
                prescription.Names = prescriptionDTO.Names;
                prescription.Reason = prescriptionDTO.Reason;
                prescription.ApplicationTime = DateTime.Now;
                prescription.Status = 0; // 待审核
                
                // 3. 计算总价并添加明细
                decimal total = 0;
                List<PrescriptionDetailModel> details = new List<PrescriptionDetailModel>();
                
                foreach (var item in prescriptionDTO.Details)
                {
                    decimal price = 0;
                    string itemName = "";
                    
                    switch (item.ItemType)
                    {
                        case 1: // 药品
                            var drug = _drugInfoRepository.GetAll().FirstOrDefault(d => d.Id == item.ItemId);
                            if (drug == null)
                                throw new ArgumentException($"未找到ID为{item.ItemId}的药品");
                                
                            // 检查库存
                            if (item.Quantity > drug.Quantity)
                                throw new InvalidOperationException($"药品 {drug.DrugName} 库存不足，当前库存: {drug.Quantity}");
                                
                            price = drug.Price;
                            itemName = drug.DrugName;
                            
                            // 更新库存
                            drug.Quantity -= item.Quantity;
                            _drugInfoRepository.Update(drug);
                            break;
                            
                        case 2: // 检查
                            var checkup = _checkupItemRepository.GetAll().FirstOrDefault(c => c.Id == item.ItemId);
                            if (checkup == null)
                                throw new ArgumentException($"未找到ID为{item.ItemId}的检查项目");
                                
                            // 检查库存
                            if (item.Quantity > checkup.Quantity)
                                throw new InvalidOperationException($"检查项目 {checkup.CheckupItemName} 数量不足，当前可用: {checkup.Quantity}");
                                
                            price = checkup.Price;
                            itemName = checkup.CheckupItemName;
                            
                            // 更新库存
                            checkup.Quantity -= item.Quantity;
                            _checkupItemRepository.Update(checkup);
                            break;
                            
                        case 3: // 检验
                            var test = _testItemRepository.GetAll().FirstOrDefault(t => t.Id == item.ItemId);
                            if (test == null)
                                throw new ArgumentException($"未找到ID为{item.ItemId}的检验项目");
                                
                            // 检查库存
                            if (item.Quantity > test.Quantity)
                                throw new InvalidOperationException($"检验项目 {test.TestItem} 数量不足，当前可用: {test.Quantity}");
                                
                            price = test.Price;
                            itemName = test.TestItem;
                            
                            // 更新库存
                            test.Quantity -= item.Quantity;
                            _testItemRepository.Update(test);
                            break;
                            
                        default:
                            throw new ArgumentException($"无效的项目类型: {item.ItemType}");
                    }
                    
                    // 累计总价
                    decimal itemTotal = price * item.Quantity;
                    total += itemTotal;
                    
                    // 创建明细
                    var detail = new PrescriptionDetailModel
                    {
                        Quantity = item.Quantity,
                        UnitPrice = price,
                        Total = itemTotal,
                        Status = 0
                    };
                    
                    // 设置对应的项目ID
                    switch (item.ItemType)
                    {
                        case 1:
                            detail.MedicineId = item.ItemId;
                            break;
                        case 2:
                            detail.ExaminationItemId = item.ItemId;
                            break;
                        case 3:
                            detail.TestItemId = item.ItemId;
                            break;
                    }
                    
                    details.Add(detail);
                }
                
                // 4. 设置总价
                prescription.Total = total;
                
                // 5. 保存开单申请
                _prescriptionRepository.Add(prescription);
                
                // 6. 保存明细记录
                foreach (var detail in details)
                {
                    detail.PrescriptionApplicationId = prescription.Id;
                    _prescriptionDetailRepository.Add(detail);
                }
                
                return prescription.Id;
            }
            catch (Exception ex)
            {
                throw new ApplicationException($"添加开单申请失败: {ex.Message}", ex);
            }
        }
        
        /// <summary>
        /// 开单确认
        /// </summary>
        /// <param name="prescriptionId">开单申请ID</param>
        /// <returns>是否确认成功</returns>
        public bool ConfirmPrescriptionApplication(long prescriptionId)
        {
            // 1. 参数检查
            if (prescriptionId <= 0)
                throw new ArgumentException("无效的开单申请ID", nameof(prescriptionId));

            try
            {
                // 2. 查找开单申请
                var prescription = _prescriptionRepository.GetAll()
                    .FirstOrDefault(p => p.Id == prescriptionId);
                
                if (prescription == null)
                    throw new ArgumentException($"未找到ID为{prescriptionId}的开单申请");
                
                // 3. 检查当前状态
                if (prescription.Status != 0) // 非待审核状态
                    throw new InvalidOperationException($"当前开单申请状态不是待审核状态，无法进行确认操作");
                
                // 4. 更新开单申请状态
                prescription.Status = 1; // 已确认
                
                _prescriptionRepository.Update(prescription);
                
                // 5. 更新开单明细状态
                var details = _prescriptionDetailRepository.GetAll()
                    .Where(d => d.PrescriptionApplicationId == prescriptionId)
                    .ToList();
                
                foreach (var detail in details)
                {
                    detail.Status = 1; // 已确认
                    _prescriptionDetailRepository.Update(detail);
                }
                
                return true;
            }
            catch (Exception ex)
            {
                throw new ApplicationException($"确认开单申请失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 显示所有检查项目分类
        /// </summary>
        /// <returns>检查项目分类列表</returns>
        public List<CheckupCategoryModel> ShowCheckupCategories()
        {
            try
            {
                // 通过仓储层获取所有检查项目分类数据
                var checkupCategories = _checkupCategoryRepository.GetAll()
                    .OrderBy(c => c.CheckupCategoryName) // 按分类名称排序
                    .ToList();
                
                return checkupCategories;
            }
            catch (Exception ex)
            {
                throw new ApplicationException($"获取检查项目分类失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 显示所有药品分类
        /// </summary>
        /// <returns>药品分类列表</returns>
        public List<DrugCategoryModel> ShowDrugCategories()
        {
            try
            {
                // 通过仓储层获取所有药品分类数据
                var drugCategories = _drugCategoryRepository.GetAll()
                    .OrderBy(c => c.CategoryName) // 按分类名称排序
                    .ToList();
                
                return drugCategories;
            }
            catch (Exception ex)
            {
                throw new ApplicationException($"获取药品分类失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 显示所有检验项目分类
        /// </summary>
        /// <returns>检验项目分类列表</returns>
        public List<TestCategoryModel> ShowTestCategories()
        {
            try
            {
                // 通过仓储层获取所有检验项目分类数据
                var testCategories = _testCategoryRepository.GetAll()
                    .OrderBy(c => c.TestCategoryName) // 按分类名称排序
                    .ToList();
                
                return testCategories;
            }
            catch (Exception ex)
            {
                throw new ApplicationException($"获取检验项目分类失败: {ex.Message}", ex);
            }
        }
       
    }
}
